﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using TakePhotoTogether.Communication.Protocols;

namespace TakePhotoTogether.Communication
{
    public class RTTController : IRemoteDataListener
    {
        private const string DEBUG_TAG = "TakePhotoTogether.Communication.RTTController => ";
        private readonly BackgroundWorker worker = new BackgroundWorker();
        private readonly SocketManager socketManager;

        private static int timeCount;
        private static double times;
        private static TimeSpan timeTripAverage;
        private const int timeAverageCount = 10;
        public static TimeSpan TimeTripAverage
        {
            get { return timeTripAverage; }
        }

        private static RTTController instance = null;

        private RTTController()
        {
            socketManager = SocketManager.GetSocketManager();
            socketManager.AddDataListener(this, (int)MessageTypes.RoundTripTimePacket);

            worker.WorkerReportsProgress = false;
            worker.WorkerSupportsCancellation = true;
            worker.DoWork += new DoWorkEventHandler(TimeMeasureLoop);
        }

        public void StartTimeMeasure()
        {
            if (!worker.IsBusy)
                worker.RunWorkerAsync();
        }

        public void StopTimeMeasure()
        {
            if (worker.IsBusy)
                worker.CancelAsync();
        }

        public static RTTController GetInstance()
        {
            if (instance == null)
            {
                instance = new RTTController();
            }
            return instance;
        }

        public static void ResetTimeTrip()
        {
            timeCount = 0;
            times = 0d;
            timeTripAverage = TimeSpan.Zero;
        }

        private void TimeMeasureLoop(object sender, DoWorkEventArgs e)
        {
            const int roundTripTimePacket = (int)MessageTypes.RoundTripTimePacket;
            BackgroundWorker worker = sender as BackgroundWorker;
            while (true)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }

                if (socketManager.GetNumberOfPacketsOnQueue(roundTripTimePacket) == 0)
                    DataPacketFactory.GetRoundTripTimePacket().Send();

                Thread.Sleep(1500);
            }
        }

        public void ReceiveData(PayloadData data)
        {
            RoundTripTimeData rttData = data as RoundTripTimeData;
            if (rttData != null)
            {
                if (rttData.returningTravel)
                {
                    TimeSpan arrive = DateTime.Now - rttData.currentTime;
                    Debug.WriteLine(DEBUG_TAG + "ReceiveData - RTT: " + arrive.TotalSeconds);

                    times += arrive.TotalMilliseconds;
                    if (++timeCount == timeAverageCount)
                    {
                        timeTripAverage = TimeSpan.FromMilliseconds(times / timeAverageCount);
                        timeCount = 0;
                        times = 0d;
                        Debug.WriteLine(DEBUG_TAG + "time avg: " + timeTripAverage.TotalSeconds);
                    }
                }
                else
                {
                    DataPacketFactory.GetRoundTripTimePacket(rttData).Send();
                }
            }
        }
    }
}
